Skip to content

feat(core): support multi-backend caplet files#177

Merged
ian-pascoe merged 5 commits into
mainfrom
codex/multi-backend-caplet-catalog
Jun 29, 2026
Merged

feat(core): support multi-backend caplet files#177
ian-pascoe merged 5 commits into
mainfrom
codex/multi-backend-caplet-catalog

Conversation

@ian-pascoe

@ian-pascoe ian-pascoe commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Caplet files can now represent a full capability suite from one CAPLET.md instead of forcing each backend into a separate catalog entry. Plural backend maps such as mcpServers, googleDiscoveryApis, openapiEndpoints, graphqlEndpoints, httpApis, cliTools, and capletSets expand into typed child Caplets while preserving a grouped parent entry for catalog and install flows.

This also turns the public catalog into a broader first-run surface: AWS, Azure, Cloudflare, Datadog, Google Workspace, MongoDB, Neon, Notion, PagerDuty, Stripe, Supabase, Terraform, and Vercel now have starter Caplets, with Google Workspace demonstrating the multi-backend suite shape across Gmail, Drive, Docs, Sheets, Slides, and Tasks.

Area What changed
File syntax Added typed plural backend maps with shared child metadata and parent/child source metadata.
Runtime/install Expands child runtime IDs as parent__child, protects direct child installs with parent-install guidance, and keeps backend validation strict.
Catalog/docs Groups multi-backend suites into one catalog parent with children, regenerates schema/docs/catalog data, and updates authoring guidance.
Docker/self-hosting Refreshes the image build for the current workspace, bakes runtime telemetry intake identifiers through build args, uses a portable pnpm deploy output, persists global config under /data/config, and points health checks at /v1/healthz.
Test stability Ignores stale virtualizer callbacks after catalog search teardown so full-suite runs do not leak async DOM work.

Validation

  • pnpm exec vitest run apps/catalog/test/virtual-results.test.ts
  • pnpm --filter @caplets/core exec vitest run test/code-mode-session.test.ts test/code-mode-sessions.test.ts test/downstream.test.ts
  • CI=true pnpm --filter @caplets/core exec vitest run test/telemetry-release.test.ts test/serve-options.test.ts test/server-options.test.ts
  • docker build --build-arg CAPLETS_POSTHOG_TOKEN=phc_docker_test --build-arg CAPLETS_RUNTIME_SENTRY_DSN=https://public@example.ingest.sentry.io/123 --build-arg CAPLETS_SENTRY_RELEASE=caplets-runtime@docker-test --build-arg CAPLETS_SENTRY_ENVIRONMENT=test -t caplets:docker-drift-check .
  • Docker image smoke checks: node dist/index.js --version, import('@caplets/core'), runtime env inspection, and live /v1/healthz check with persisted /data/config/caplets/config.json
  • pnpm verify
  • Pre-push hook reran pnpm verify successfully

Compound Engineering
GPT-5

Summary by CodeRabbit

  • New Features

    • Added support for multi-backend Caplet suites with parent/child runtime handles.
    • Expanded the official catalog with many new provider and tool entries, including cloud, database, productivity, and infrastructure capabilities.
    • Updated docs and authoring guidance with new examples and rules for suite-based Caplet files.
  • Bug Fixes

    • Improved catalog search cleanup to avoid rendering after the view is closed.
    • Better install error messages and risk detection for suite-based Caplets.
  • Tests

    • Added coverage for multi-backend loading, catalog grouping, source parsing, and install behavior.

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

An error occurred during the review process. Please try again later.

📝 Walkthrough

Walkthrough

Introduces multi-backend Caplet Markdown files that declare plural backend maps (e.g., googleDiscoveryApis, mcpServers) expanding into parent__child runtime child handles. Extends schema validation, load-time expansion, catalog integration, install risk logic, index generation, and docs. Adds twelve new official Caplet definitions (AWS, Azure, Cloudflare, Datadog, Google Workspace, MongoDB, Neon, Notion, PagerDuty, Stripe, Supabase, Terraform, Vercel) with catalog entries. Fixes a post-destroy rendering guard in the virtual catalog search.

Changes

Multi-Backend Caplet Files Feature

Layer / File(s) Summary
Plural backend schemas and exported types
packages/core/src/caplet-files-bundle.ts, packages/core/src/caplet-source/parse.ts, packages/core/src/catalog/types.ts
Zod schemas extended to validate plural backend maps with mutual-exclusivity and per-child inheritance rules. Exports CapletFileSourceMetadata; updates CapletFileLoadResult, ParsedCapletSourceCaplet (parentId/childId), CatalogEntryChild, and CatalogEntry (children).
Load-time expansion and normalization pipeline
packages/core/src/caplet-files-bundle.ts, packages/core/src/caplet-source/parse.ts
buildCapletFileLoadResultFromEntries detects expanded-caplet-file configs, generates parent__child runtime IDs, records per-child metadata, and merges inherited shared fields. capletToServerConfig routes through capletToExpandedServerConfigs. patchCapletJsonSchema extended for plural HTTP and CLI action maps. parseCapletSource reads metadata to populate parentId/childId/sourcePath.
Catalog and install risk integration for plural backends
packages/core/src/catalog/caplet-markdown.ts, packages/core/src/catalog/entry.ts, packages/core/src/cli/install.ts
catalogSetupRequired, catalogProjectBindingRequired, catalogMutatesExternalState, catalogUsesLocalControl, and catalogCapletAuthBlocks extended to traverse plural backend maps. createCatalogEntry conditionally emits children. installCaplets adds child-install guidance; riskSummaryForSourcePath, capletBackendFamilies, capletAuthBlocks, capletCanMutate, and capletCanDestroy all handle plural keys via new helper utilities.
Catalog index and docs-reference generation for suites
scripts/generate-catalog-index.ts, scripts/generate-docs-reference.ts
generateOfficialCatalogEntries groups caplets by (sourcePath, parentId) into suite groups, emitting one parent entry with a children array. workflowSummary generalized to caplet arrays. Docs-reference generation adds the Google Workspace provider suite example.
Tests
packages/core/test/caplet-files.test.ts, packages/core/test/caplet-source.test.ts, packages/core/test/catalog-model.test.ts, packages/core/test/catalog-official-index.test.ts, packages/core/test/cli.test.ts, packages/core/test/config.test.ts
New positive test for googleDiscoveryApis expansion into runtime child IDs. Negative tests for mixed singular/plural, invalid cliTools plural, and unsupported child fields. Source metadata preservation, catalog suite grouping, runtime child ID rejection, lockfile aggregation, and union CLI schema discovery are all tested.
Docs, authoring skill, plan, and changeset
apps/docs/src/content/docs/reference/caplet-files.mdx, skills/writing-caplets/SKILL.md, CONCEPTS.md, docs/plans/..., .changeset/...
Reference docs add provider suite example and plural field reference sections for all backend families. Skill adds multi-backend authoring rule and checklist bullet. Concepts adds glossary entry. Changeset marks minor. Full implementation plan document added.

New Official Caplet Definitions

Layer / File(s) Summary
New CAPLET.md definitions
caplets/aws/CAPLET.md, caplets/azure/CAPLET.md, caplets/cloudflare/CAPLET.md, caplets/datadog/CAPLET.md, caplets/google-workspace/CAPLET.md, caplets/mongodb/CAPLET.md, caplets/neon/CAPLET.md, caplets/notion/CAPLET.md, caplets/pagerduty/CAPLET.md, caplets/stripe/CAPLET.md, caplets/supabase/CAPLET.md, caplets/terraform/CAPLET.md, caplets/vercel/CAPLET.md
Adds CAPLET.md files for thirteen providers. Google Workspace uses the new plural googleDiscoveryApis multi-backend syntax with six child surfaces; others use singular MCP/OAuth or Docker-based configurations, each with operator workflow and safety guidance.
Official catalog JSON entries
apps/catalog/src/data/official-catalog.json
Adds catalog JSON objects for all new providers including the Google Workspace suite entry (with children array and set workflow kind), plus entries for AWS, Azure, Cloudflare, Datadog, MongoDB, Neon, Notion, PagerDuty, Stripe, Supabase, Terraform, and Vercel.

Virtual Catalog Search Lifecycle Fix

Layer / File(s) Summary
Post-destroy rendering guard
apps/catalog/src/scripts/virtual-results.ts
Adds a destroyed boolean flag; onChange handler and renderVirtualRows check it before executing; destroy() sets the flag before cleanup.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

  • spiritledsoftware/caplets#52: Implements the capletSets/capletSet nested-caplet backend via CapletSetManager; this PR extends plural multi-backend handling to include capletSets as a recognized plural backend family.
  • spiritledsoftware/caplets#126: Introduces the googleDiscoveryApis backend configuration, which this PR's expansion pipeline explicitly handles as a plural backend family with parent__child runtime ID generation.
  • spiritledsoftware/caplets#167: Modifies installCaplets risk computation and lockfile behavior in the same packages/core/src/cli/install.ts code paths that this PR further extends for plural backend frontmatter shapes.

Poem

🐇 Hop, hop — one file, many friends inside!
Plural maps expand, child handles identified.
workspace__drive, workspace__gmail — each gets its own key,
The parent installs all, the children come to play.
From AWS to Vercel, the catalog grows wide,
A rabbit's best work, with nothing to hide! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely matches the main change: adding multi-backend caplet file support.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/multi-backend-caplet-catalog

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

@greptile-apps

greptile-apps Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds multi-backend support to Caplet files, allowing a single CAPLET.md to declare multiple backends (e.g. googleDiscoveryApis, httpApis, mcpServers) that expand into typed child Caplets at runtime with parent__child IDs. It also ships 13 new official catalog entries and refreshes the Docker build to use pnpm deploy output with baked telemetry tokens.

  • Schema & expansion: New plural backend map schemas with superRefine cross-family child-ID uniqueness enforcement; shared parent fields (auth, name, tags, setup, runtime) are inherited and merged into each child during load via capletToExpandedServerConfigs.
  • Install & catalog: installCaplets now detects direct child-ID installs and emits parent-install guidance; risk metadata (auth scopes, runtime features, destructive hints) is aggregated across all plural backends; official catalog generation groups child entries under a single parent with a \"Capability suite\" workflow label.
  • Infrastructure: Docker image switches to a portable pnpm deploy output directory, health-check URL corrected to /v1/healthz, and Sentry/PostHog tokens baked in via build args.

Confidence Score: 5/5

The change is safe to merge; all new code paths are guarded by Zod schema validation, and the PR ships comprehensive tests covering expansion, install guidance, catalog grouping, and risk aggregation.

The core expansion logic is well-factored with cross-family uniqueness checked in superRefine. Auth inheritance between capletEndpointAuthSchema and capletRemoteAuthSchema is safe because both schemas are structurally identical discriminated unions. No silent data-loss paths were identified.

caplet-files-bundle.ts warrants a second look on the implicit MCP backend fallback — the absence of an explicit backend: mcp field in expanded MCP child configs is correct but relies on an undocumented convention shared between configBackend and addConfig.

Important Files Changed

Filename Overview
packages/core/src/caplet-files-bundle.ts Core schema and expansion logic for multi-backend caplet files. Well-structured with cross-family uniqueness validation in superRefine, correct dual-underscore child runtime ID derivation, and idiomatic shared-field inheritance/merging. The implicit MCP fallback in configBackend/addConfig is functionally correct but relies on an undocumented invariant.
packages/core/src/cli/install.ts Adds child-install guidance, risk aggregation across plural backend families, and catalog child population for installed lock entries. Auth scope and runtime-feature deduplication handled correctly with Set. Logic for loading metadata for community-installed suites is functionally sound with a best-effort silent fallback.
packages/core/src/catalog/caplet-markdown.ts Extends catalog helpers to detect plural backend maps. catalogWorkflowSummaryFromFrontmatter correctly gates on catalogHasPluralBackendMap, fixing previously reported mislabeling for community caplets.
scripts/generate-catalog-index.ts Adds groupedCatalogCaplets to collapse child entries into a single parent catalog entry. Grouping key is correct, list is sorted deterministically, and parent metadata is sourced from frontmatter for suite entries.
apps/catalog/src/scripts/virtual-results.ts Adds a destroyed flag guarding virtualizer callbacks after teardown, preventing async DOM mutations after catalog search is closed.
Dockerfile Switches to pnpm deploy output for a portable /deploy directory, bakes telemetry tokens via build args using JSON.stringify, and fixes health check path to /v1/healthz.
packages/core/src/caplet-source/parse.ts Propagates parentId and childId from loaded metadata into ParsedCapletSourceCaplet. Gracefully falls back to caplet.server when metadata is absent.
packages/core/src/catalog/types.ts Adds CatalogEntryChild type and optional children field to CatalogEntryInput and CatalogEntry. Clean additive change.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["CAPLET.md\n(plural backend syntax)"] --> B["capletFileSchema.superRefine\n• cross-family child ID uniqueness\n• singular vs plural mutual exclusion\n• auth scope restriction"]
    B --> C["capletToExpandedServerConfigs"]
    C --> D["addExpandedChildren per backend family"]
    D --> E["splitChildBackendConfig"]
    E --> F["mergeSharedCapletFields"]
    F --> G["validateExpandedBackendConfig"]
    G --> H["normalizeExpandedBackendConfig"]
    H --> I["ExpandedCapletFileConfig"]
    I --> J["buildCapletFileLoadResultFromEntries\naddConfig(parent__child, config)"]
    J --> K["CapletFileLoadResult\n{config, paths, metadata}"]
    K --> L1["installCaplets\nrisk aggregation"]
    K --> L2["parseCapletSource\nparentId + childId"]
    K --> L3["catalogChildrenForInstalledLockEntry"]
    L2 --> O["generateOfficialCatalogEntries\ngroupedCatalogCaplets"]
    O --> P["CatalogEntry\nworkflow=Capability suite\nchildren=[CatalogEntryChild, ...]"]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A["CAPLET.md\n(plural backend syntax)"] --> B["capletFileSchema.superRefine\n• cross-family child ID uniqueness\n• singular vs plural mutual exclusion\n• auth scope restriction"]
    B --> C["capletToExpandedServerConfigs"]
    C --> D["addExpandedChildren per backend family"]
    D --> E["splitChildBackendConfig"]
    E --> F["mergeSharedCapletFields"]
    F --> G["validateExpandedBackendConfig"]
    G --> H["normalizeExpandedBackendConfig"]
    H --> I["ExpandedCapletFileConfig"]
    I --> J["buildCapletFileLoadResultFromEntries\naddConfig(parent__child, config)"]
    J --> K["CapletFileLoadResult\n{config, paths, metadata}"]
    K --> L1["installCaplets\nrisk aggregation"]
    K --> L2["parseCapletSource\nparentId + childId"]
    K --> L3["catalogChildrenForInstalledLockEntry"]
    L2 --> O["generateOfficialCatalogEntries\ngroupedCatalogCaplets"]
    O --> P["CatalogEntry\nworkflow=Capability suite\nchildren=[CatalogEntryChild, ...]"]
Loading

Reviews (4): Last reviewed commit: "fix(core): validate plural child id coll..." | Re-trigger Greptile

Comment thread packages/core/src/caplet-files-bundle.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/docs/src/content/docs/reference/caplet-files.mdx`:
- Line 232: The auth field descriptions in the backend config tables are
copy-paste leftovers and still mention the wrong generic endpoint types. Update
the `auth` row text in the affected sections for `openapiEndpoints`,
`googleDiscoveryApis`, `graphqlEndpoints`, and `httpApis` so each uses the
matching backend-specific singular description; keep the change localized to the
table entries in the docs content.
- Around line 375-378: The cliTools docs are missing the plural child-field
table and the reserved actions guidance, which can cause incorrect authoring of
plural backend configs. Update the cliTools section to document the plural shape
as a child-ID map and add a note that actions is reserved as a child ID, not a
valid child identifier. Include the per-child fields (actions, disabled,
projectBinding, runtime) plus the capability metadata fields (name, description,
tags, exposure, shadowing, useWhen, avoidWhen, setup) so readers can distinguish
plural cliTools from the singular form.

In `@packages/core/src/caplet-files-bundle.ts`:
- Around line 1097-1123: Keep expanded-child runtime ID validation inside the
warning-mode boundary in caplet-files-bundle’s expanded-child handling. The
current child loop in the config expansion path validates childRuntimeId before
the try/catch, which can abort best-effort loading for an oversized
parent__child ID instead of warning and skipping just that child. Move the
validateCapletId check for childRuntimeId into the same warning-handled section
as addConfig, matching the singular addConfig path’s warning-mode behavior for
conflicting IDs.
- Around line 755-761: The plural backend map schema in
capletPluralBackendMapSchema enforces non-empty objects at runtime via refine,
but patchCapletJsonSchema is not mirroring that constraint for the plural map
properties. Update the JSON Schema patching logic to add minProperties for
mcpServers, openapiEndpoints, googleDiscoveryApis, graphqlEndpoints, httpApis,
and capletSets so the generated schema matches the runtime validation behavior.

In `@packages/core/src/cli/install.ts`:
- Around line 968-970: The capletAuth helper is picking the first auth block
from capletAuthBlocks(), which can let a top-level or first-child type: "none"
hide a later required OAuth/API-key backend. Update capletAuth to prefer a
required auth block when present and only fall back to none if no required block
exists, using capletAuthBlocks and derivedSafety(auth) as the key call sites to
preserve the intended auth selection.
- Around line 651-653: The guidance message in the install flow only reports
runtime child Caplet IDs and drops any unmatched missing IDs. Update the logic
around the `missingIds` handling in `install.ts` so the returned error message
includes both the `matches` child entries and any truly missing IDs that were
not matched, using the same install guidance path that builds the Caplet install
error. Keep the child-specific text for `match.id -> match.parentId`, but append
the non-child IDs so users see every problematic ID.

In `@packages/core/test/config.test.ts`:
- Around line 3289-3299: findUnionCliActionsSchema currently only looks for
actions under variant.properties.actions, so it misses plural cliTools variants
when cliTools is nested inside anyOf/oneOf. Update the fallback in
findUnionCliActionsSchema to mirror the direct schemaPath handling for cliTools
by checking the plural branch shape (additionalProperties.properties.actions) as
well as the existing singular branch, using the existing schemaPath helper and
the findUnionCliActionsSchema symbol to locate the logic.

In `@scripts/generate-catalog-index.ts`:
- Line 93: The suite tag assignment in generate-catalog-index.ts currently drops
inherited tags when frontmatter.tags is missing. Update the logic around the
tags field in the catalog entry निर्माण so suite entries fall back to the parsed
caplet.config.tags when catalogStringArrayFromFrontmatter(frontmatter.tags) is
undefined or empty, while preserving the existing behavior for non-suite
entries.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6f8367d4-bb2d-48fa-b07b-05102a639d46

📥 Commits

Reviewing files that changed from the base of the PR and between 23c7bcf and 51cc65a.

📒 Files selected for processing (36)
  • .changeset/multi-backend-caplet-files.md
  • CONCEPTS.md
  • apps/catalog/src/data/official-catalog.json
  • apps/catalog/src/scripts/virtual-results.ts
  • apps/docs/src/content/docs/reference/caplet-files.mdx
  • apps/landing/public/caplet.schema.json
  • caplets/aws/CAPLET.md
  • caplets/azure/CAPLET.md
  • caplets/cloudflare/CAPLET.md
  • caplets/datadog/CAPLET.md
  • caplets/google-workspace/CAPLET.md
  • caplets/mongodb/CAPLET.md
  • caplets/neon/CAPLET.md
  • caplets/notion/CAPLET.md
  • caplets/pagerduty/CAPLET.md
  • caplets/stripe/CAPLET.md
  • caplets/supabase/CAPLET.md
  • caplets/terraform/CAPLET.md
  • caplets/vercel/CAPLET.md
  • docs/plans/2026-06-29-001-feat-multi-backend-caplet-files-plan.md
  • packages/core/src/caplet-files-bundle.ts
  • packages/core/src/caplet-source/parse.ts
  • packages/core/src/catalog/caplet-markdown.ts
  • packages/core/src/catalog/entry.ts
  • packages/core/src/catalog/types.ts
  • packages/core/src/cli/install.ts
  • packages/core/test/caplet-files.test.ts
  • packages/core/test/caplet-source.test.ts
  • packages/core/test/catalog-model.test.ts
  • packages/core/test/catalog-official-index.test.ts
  • packages/core/test/cli.test.ts
  • packages/core/test/config.test.ts
  • schemas/caplet.schema.json
  • scripts/generate-catalog-index.ts
  • scripts/generate-docs-reference.ts
  • skills/writing-caplets/SKILL.md

Comment thread apps/docs/src/content/docs/reference/caplet-files.mdx Outdated
Comment thread apps/docs/src/content/docs/reference/caplet-files.mdx
Comment thread packages/core/src/caplet-files-bundle.ts
Comment thread packages/core/src/caplet-files-bundle.ts Outdated
Comment thread packages/core/src/cli/install.ts Outdated
Comment thread packages/core/src/cli/install.ts
Comment thread packages/core/test/config.test.ts
Comment thread scripts/generate-catalog-index.ts Outdated
Comment thread packages/core/src/caplet-files-bundle.ts
@ian-pascoe ian-pascoe merged commit b371d0b into main Jun 29, 2026
7 checks passed
@ian-pascoe ian-pascoe deleted the codex/multi-backend-caplet-catalog branch June 29, 2026 20:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant